package com.john.blog.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.john.blog.common.constant.DateStyle;
import com.john.blog.common.constant.KeyConst;
import com.john.blog.common.vo.FtpConfig;
import com.john.blog.common.vo.RemoteConfig;
import com.john.blog.model.po.Blog;
import com.john.blog.service.BlogService;

import freemarker.template.Configuration;
import freemarker.template.Template;
import tk.mybatis.mapper.entity.Example;

/**
 * 正文静态化工具类
 * 
 * @author JiangGengchao
 * @date 2018年2月25日
 */
public class StaticsUtils {

    private static final String URL = "javascript:;";
    private static final String MSG = "无";
    private static final String YYYY_MM_DD = "yyyy-MM-dd";
    private static final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
    private static final Object object = new Object();

    /**
     * 生成静态化的HTML的文件路径
     * 
     * @return
     */
    public static String genHtmlFilePath(String filename) {
        return FileUtils.getProjectBasePath() + filename;
    }

    /**
     * 使用时间生成博文的文件名，精确到秒
     * 
     * 
     * @param date
     * @return
     */
    public static String genHtmlFileName(Date date) {
        if (date == null) {
            date = new Date();
        }
        String prefix = "B" + DateUtils.DateToString(date, DateStyle.YYYYMMDDHHMMSS);
        return prefix + ".html";
    }

    private static SimpleDateFormat getDateFormat(String pattern) throws RuntimeException {
        SimpleDateFormat dateFormat = threadLocal.get();
        if (dateFormat == null) {
            synchronized (object) {
                if (dateFormat == null) {
                    dateFormat = new SimpleDateFormat(pattern);
                    dateFormat.setLenient(false);
                    threadLocal.set(dateFormat);
                }
            }
        }
        dateFormat.applyPattern(pattern);
        return dateFormat;
    }

    public static String dateToString(Date date, String pattern) {
        String dateString = null;
        if (date != null) {
            try {
                dateString = getDateFormat(pattern).format(date);
            } catch (Exception e) {
            }
        }
        return dateString;
    }

    /**
     * 博客内容静态化渲染方法
     * 
     * @param service
     * @param bean
     * @return
     * @throws Exception
     */
    public static boolean render(RemoteConfig remoteConfig, String baseServer, BlogService service, Blog bean) throws Exception {
        Map<String, Object> t = prepareData(remoteConfig, baseServer, service, bean);
        generator(remoteConfig, service, bean.getRemoteUrl(), t);
        return true;
    }

    /**
     * 渲染前的数据准备
     * 
     * @param service
     * @param bean
     * @return
     */
    private static Map<String, Object> prepareData(RemoteConfig remoteConfig, String baseServer, BlogService service, Blog bean) {
        Map<String, Object> t = new HashMap<>();
        t.put("staticSource", KeyConst.STATIC_SOURCE);
        t.put("base", remoteConfig.getRemoteServer());
        t.put("baseServer", baseServer);
        t.put("system", "front");
        t.put("id", bean.getId());
        t.put("name", bean.getName());
        t.put("author", bean.getAuthor());
        String createDate = dateToString(bean.getCreateDate(), YYYY_MM_DD);
        t.put("createDate", createDate);
        String updateDate = dateToString(bean.getUpdateDate(), YYYY_MM_DD);
        t.put("updateDate", updateDate);
        t.put("signature", bean.getSignature());
        t.put("url", bean.getUrl());
        t.put("path", bean.getRemoteUrl());
        t.put("picture", bean.getPicture());
        t.put("tags", bean.getTags());
        t.put("categoryID", bean.getCategoryID());
        t.put("status", bean.getStatus().toString());
        t.put("summary", bean.getSummary());
        t.put("commentNum", bean.getCommentNum().toString());
        t.put("readNum", bean.getReadNum().toString());
        t.put("shareNum", bean.getShareNum().toString());
        t.put("heartNum", bean.getHeartNum().toString());
        t.put("content", bean.getContent());
        t.put("html", bean.getHtml());
        t.put("categoryName", bean.getCategoryName());
        t.put("statusName", bean.getStatusName());

        // 查找
        Example example = new Example(Blog.class);
        example.orderBy("createDate");
        List<Blog> blogs = service.selectByExample(example);
        Blog preBlog = null;
        Blog nextBlog = null;
        boolean flag = false;
        for (Blog curBlog : blogs) {
            if (curBlog.getId().equals(bean.getId())) {
                flag = true;
            } else {
                if (flag && null == nextBlog) {
                    nextBlog = curBlog;
                } else {
                    preBlog = curBlog;
                }
            }
        }
        if (nextBlog == null) {
            t.put("nextURL", URL);
            t.put("nextTitle", MSG);
        } else {
            t.put("nextURL", nextBlog.getUrl());
            t.put("nextTitle", nextBlog.getName());
        }
        if (preBlog == null) {
            t.put("preURL", URL);
            t.put("preTitle", MSG);
        } else {
            t.put("preURL", preBlog.getUrl());
            t.put("preTitle", preBlog.getName());
        }
        List<String> blogTags = new ArrayList<String>();
        if (bean.getTags() != null) {
            String[] arr = bean.getTags().split(",");
            for (String tag : arr) {
                blogTags.add(tag);
            }
        }
        t.put("blogTags", blogTags);
        return t;
    }

    /**
     * 生成静态文件方法
     * 
     * @param service
     * @param path
     * @param t
     * @throws IOException
     */
    private static void generator(RemoteConfig remoteConfig, BlogService service, String remoteUrl, Map<String, Object> t) throws Exception {
        // 读取模板
        Configuration config = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        config.setDefaultEncoding("UTF-8");
        config.setDirectoryForTemplateLoading(new File(remoteConfig.getConfigPath()));
        Template template = config.getTemplate("template.ftl");
        // 写入模板
        File file = new File(remoteConfig.getConfigPath() + File.separator + remoteUrl.substring(remoteUrl.lastIndexOf("/") + 1));
        FileWriter writer = new FileWriter(file);
        template.process(t, writer);
        writer.close();
        InputStream input = new FileInputStream(file);
        // 上传ftp
        FtpConfig ftpConfig = new FtpConfig(remoteConfig.getRemoteServer().split("//")[1], remoteConfig.getRemotePort(), remoteConfig.getRemoteUsername(), remoteConfig.getRemotePassword(),
                remoteConfig.getDefaultPath() + KeyConst.TEMPLATE_PATH, "utf-8");
        if (!FtpUtil.uploadFile(ftpConfig, remoteUrl.substring(remoteUrl.lastIndexOf("/") + 1), input)) {
            input.close();
            // 删除临时文件
            FileUtils.deleteFile(file);
            throw new RuntimeException("静态化文件上传失败");
        } else {
            input.close();
            // 删除临时文件
            FileUtils.deleteFile(file);
        }
    }

}
